﻿package com.gengine.resource
{
    import __AS3__.vec.*;
    import com.gengine.core.call.*;
    import com.gengine.core.frame.*;
    import com.gengine.debug.*;
    import com.gengine.global.*;
    import com.gengine.resource.info.*;
    import com.gengine.resource.loader.*;
    import com.gengine.utils.pools.*;
    import flash.events.*;
    import flash.utils.*;

    public class LoaderManager extends Object
    {
        private var _completeCaller:Caller;
        private var _progressCaller:Caller;
        private var _errorCaller:Caller;
        public var createInfoFun:Function;
        private var _maxQueue:int = 1;
        private var _queueMap:Dictionary;
        private var _currentCount:int = 0;
        private var _queueArray0:Array;
        private var _queueArray1:Array;
        private var _queueArray2:Array;
        private var _queueArray3:Array;
        private var _queues:Vector.<Array>;
        private var _frameQueue:Array;
        private var _lastFrame:int;
        private var _timer:FrameTimer;
        private var _preloadingInfo:ResourceInfo;
        public var delayCallCompleteTime:Number = 0;
        public var startCalculate:Boolean = false;
        public var _hasLoadSizeList:Dictionary;
        public var _hasLoadNameList:Array;
        private static var _instance:LoaderManager = new LoaderManager;
        private static var _errorMap:Dictionary = new Dictionary(false);

        public function LoaderManager()
        {
            this._queues = new Vector.<Array>;
            this._hasLoadSizeList = new Dictionary(false);
            this._hasLoadNameList = new Array();
            if (_instance != null)
            {
                throw new Error("LoaderManager 单例  ");
            }
            this._queueArray0 = [];
            this._queueArray1 = [];
            this._queueArray2 = [];
            this._queueArray3 = [];
            this._queues.push(this._queueArray0);
            this._queues.push(this._queueArray1);
            this._queues.push(this._queueArray2);
            this._queues.push(this._queueArray3);
            this._frameQueue = [];
            this._completeCaller = new Caller();
            this._progressCaller = new Caller();
            this._errorCaller = new Caller();
            this._timer = new FrameTimer(1, int.MAX_VALUE, true);
            this._timer.addListener(TimerType.ENTERFRAME, this.onEnterFrame);
            this._timer.start();
            this._maxQueue = Global.maxQueue;
            return;
        }// end function

        public function load(param1:String, param2:Function, param3:int = 1, param4:Object = null, param5:Function = null, param6:Function = null) : ResourceInfo
        {
            var _loc_7:* = ResourceManager.getInfoByName(param1);
            if (_loc_7 == null && this.createInfoFun != null)
            {
                _loc_7 = this.createInfoFun(param1);
            }
            if (_loc_7 == null)
            {
                Log.debugMsg(LogType.other, param1 + "==没有该文件");
                if (param6 is Function)
                {
                    this.param6(_loc_7);
                }
            }
            else
            {
                this.loadInfo(_loc_7, param2, param3, param4, param5, param6);
            }
            return _loc_7;
        }// end function

        public function removeNotLoadedFile(param1:String) : void
        {
            this.clearLoadFileByName(param1);
            return;
        }// end function

        public function loadInfo(param1:ResourceInfo, param2:Function, param3:int = 3, param4:Object = null, param5:Function = null, param6:Function = null) : void
        {
            if (param4)
            {
                param1.extData = param4;
            }
            if (param1.isLoaded)
            {
                param1.addReference();
                return;
            }
            if (param1.isLoading)
            {
                this._completeCaller.addCall(param1.name, param2);
                if (param5 is Function)
                {
                    this._progressCaller.addCall(param1.name, param5);
                }
                if (param6 is Function)
                {
                    this._errorCaller.addCall(param1.name, param6);
                }
            }
            else if (param1.isPreLoading)
            {
                if (!this._preloadingInfo)
                {
                    this._preloadingInfo = param1;
                    this._completeCaller.addCall(param1.name, param2);
                    if (param5 is Function)
                    {
                        this._progressCaller.addCall(param1.name, param5);
                    }
                    if (param6 is Function)
                    {
                        this._errorCaller.addCall(param1.name, param6);
                    }
                    PreLoaderManager.instance.addLoadedCall(param1.name, this.loadPreRes);
                    PreLoaderManager.instance.addErrorCall(param1.name, this.loadPreRes);
                }
            }
            else
            {
                this._completeCaller.addCall(param1.name, param2);
                if (param5 is Function)
                {
                    this._progressCaller.addCall(param1.name, param5);
                }
                if (param6 is Function)
                {
                    this._errorCaller.addCall(param1.name, param6);
                }
                this.addLoader(param1, param3);
            }
            return;
        }// end function

        private function loadPreRes() : void
        {
            if (this._preloadingInfo)
            {
                this.loadResource(this._preloadingInfo, true);
                this._preloadingInfo = null;
            }
            return;
        }// end function

        private function onEnterFrame(param1:FrameTimer) : void
        {
            var _loc_2:ResourceInfo = null;
            if (this._frameQueue.length > 0)
            {
                _loc_2 = this._frameQueue.shift();
                this.loaderInfo(_loc_2);
            }
            return;
        }// end function

        private function canLoadResource(param1:Boolean = false) : Boolean
        {
            if (this._currentCount < this._maxQueue || param1)
            {
                return true;
            }
            return false;
        }// end function

        private function loadResource(param1:ResourceInfo, param2:Boolean = false) : Boolean
        {
            var _loc_4:int = 0;
            if (!this.canLoadResource(param2))
            {
                return false;
            }
            var _loc_3:* = FileType.getLoaderByType(param1.type);
            if (_loc_3)
            {
                var _loc_5:String = this;
                var _loc_6:* = this._currentCount + 1;
                _loc_5._currentCount = _loc_6;
                param1.isLoading = true;
                _loc_4 = (FrameManager.flashFrame as FlashFrame).rendererCount;
                if (this._lastFrame == _loc_4)
                {
                    this._frameQueue.push(param1);
                }
                else
                {
                    this._lastFrame = _loc_4;
                    this.loaderInfo(param1);
                }
            }
            else
            {
                param1.isLoading = false;
                Log.debugMsg(LogType.other, param1.name + ",不支持该类型文件");
                this.loadNext();
            }
            return true;
        }// end function

        private function loaderInfo(param1:ResourceInfo) : void
        {
            var _loc_2:Class = null;
            var _loc_3:BaseLoader = null;
            if (_errorMap[param1.path] == true)
            {
                this.onIOErrorHandler(null, param1);
            }
            else
            {
                _loc_2 = FileType.getLoaderByType(param1.type);
                if (_loc_2)
                {
                    if (this.startCalculate)
                    {
                        this._hasLoadNameList.push(param1.name);
                    }
                    _loc_3 = ObjectPool.getObject(_loc_2);
                    _loc_3.addEventListener(Event.COMPLETE, this.onCompleteHandler);
                    _loc_3.addEventListener(ProgressEvent.PROGRESS, this.onProgressHandler);
                    _loc_3.addEventListener(LoaderErrorEvent.LoaderError, this.onIOErrorHandler);
                    _loc_3.load(param1.path, param1);
                }
            }
            return;
        }// end function

        private function addLoader(param1:ResourceInfo, param2:int = 3) : void
        {
            if (this.loadResource(param1) == false)
            {
                this.addQueue(param1, param2);
                param1.isLoading = true;
            }
            return;
        }// end function

        private function addQueue(param1:ResourceInfo, param2:int = 0) : void
        {
            if (param1.isLoadedByteArray() || param1.isHasLoaded)
            {
                param2 = 0;
            }
            if (param2 >= 3)
            {
                this._queueArray3.push(param1);
            }
            else if (param2 == 0)
            {
                this._queueArray0.push(param1);
            }
            else if (param2 == 1)
            {
                this._queueArray1.push(param1);
            }
            else if (param2 == 2)
            {
                this._queueArray2.push(param1);
            }
            return;
        }// end function

        private function shiftQueue() : ResourceInfo
        {
            var _loc_1:ResourceInfo = null;
            var _loc_2:int = 0;
            var _loc_3:Array = null;
            _loc_2 = 0;
            while (_loc_2 < this._queues.length)
            {
                
                _loc_3 = this._queues[_loc_2] as Array;
                if (_loc_3.length > 0)
                {
                    return _loc_3.shift() as ResourceInfo;
                }
                _loc_2++;
            }
            return null;
        }// end function

        private function onCompleteHandler(event:Event) : void
        {
            var _loc_2:* = event.target as BaseLoader;
            if (this.delayCallCompleteTime > 0)
            {
                _loc_2.delayId = setTimeout(this.onTimeOutCompleteHander, this.delayCallCompleteTime, _loc_2);
            }
            else
            {
                this.onTimeOutCompleteHander(_loc_2);
            }
            return;
        }// end function

        private function onTimeOutCompleteHander(param1:BaseLoader) : void
        {
            param1.delayId = -1;
            var _loc_2:String = this;
            var _loc_3:* = this._currentCount - 1;
            _loc_2._currentCount = _loc_3;
            param1.removeEventListener(Event.COMPLETE, this.onCompleteHandler);
            param1.removeEventListener(ProgressEvent.PROGRESS, this.onProgressHandler);
            param1.removeEventListener(LoaderErrorEvent.LoaderError, this.onIOErrorHandler);
            if (param1.resourceInfo)
            {
                param1.resourceInfo.addReference();
                this._completeCaller.call(param1.resourceInfo.name, param1.resourceInfo);
                this._completeCaller.removeCallByType(param1.resourceInfo.name);
                this._progressCaller.removeCallByType(param1.resourceInfo.name);
                this._errorCaller.removeCallByType(param1.resourceInfo.name);
            }
            param1.dispose();
            ObjectPool.disposeObject(param1);
            this.loadNext();
            return;
        }// end function

        private function loadNext() : void
        {
            var _loc_1:ResourceInfo = null;
            if (this._frameQueue.length > 0)
            {
                this.loaderInfo(this._frameQueue.shift() as ResourceInfo);
                return;
            }
            if (this.canLoadResource())
            {
                _loc_1 = this.shiftQueue();
                if (_loc_1)
                {
                    this.loadResource(_loc_1);
                }
            }
            else if (!this._preloadingInfo)
            {
                PreLoaderManager.instance.start();
            }
            return;
        }// end function

        private function onProgressHandler(event:ProgressEvent) : void
        {
            var _loc_2:* = event.target as BaseLoader;
            if (_loc_2.resourceInfo)
            {
                this._progressCaller.call(_loc_2.resourceInfo.name, event);
            }
            if (this.startCalculate)
            {
                this._hasLoadSizeList[_loc_2.resourceInfo.name] = event.bytesTotal;
            }
            return;
        }// end function

        private function onIOErrorHandler(event:LoaderErrorEvent, param2:ResourceInfo = null) : void
        {
            var _loc_3:BaseLoader = null;
            var _loc_4:String = this;
            var _loc_5:* = this._currentCount - 1;
            _loc_4._currentCount = _loc_5;
            if (event != null)
            {
                _loc_3 = event.target as BaseLoader;
                _loc_3.removeEventListener(Event.COMPLETE, this.onCompleteHandler);
                if (_loc_3.delayId >= 0)
                {
                    clearTimeout(_loc_3.delayId);
                    _loc_3.delayId = -1;
                }
                _loc_3.removeEventListener(ProgressEvent.PROGRESS, this.onProgressHandler);
                _loc_3.removeEventListener(LoaderErrorEvent.LoaderError, this.onIOErrorHandler);
                param2 = _loc_3.resourceInfo;
                Log.debugMsg(LogType.other, "LoaderManager.onIOErrorHandler ->" + event.text);
            }
            if (param2)
            {
                param2.dispose();
                this._errorCaller.call(param2.name, param2);
                this._completeCaller.removeCallByType(param2.name);
                this._progressCaller.removeCallByType(param2.name);
                this._errorCaller.removeCallByType(param2.name);
                _errorMap[param2.path] = true;
            }
            if (_loc_3)
            {
                _loc_3.dispose();
                ObjectPool.disposeObject(_loc_3);
            }
            this.loadNext();
            return;
        }// end function

        public function removeResourceEvent(param1:String, param2:Function, param3:Function = null, param4:Function = null) : void
        {
            if (param2 is Function)
            {
                this._completeCaller.removeCall(param1, param2);
            }
            if (param3 is Function)
            {
                this._progressCaller.removeCall(param1, param3);
            }
            if (param4 is Function)
            {
                this._errorCaller.removeCall(param1, param4);
            }
            return;
        }// end function

        public function isLoading() : Boolean
        {
            return this._currentCount != 0;
        }// end function

        public function disposeFile(param1:String) : void
        {
            var _loc_2:* = ResourceManager.getInfoByName(param1);
            if (_loc_2)
            {
                _loc_2.dispose();
            }
            return;
        }// end function

        public function clearLoadFileByName(param1:String) : void
        {
            var _loc_2:* = ResourceManager.getInfoByName(param1);
            if (_loc_2)
            {
                this.clearLoadFileByInfo(_loc_2);
            }
            return;
        }// end function

        public function clearLoadFileByInfo(param1:ResourceInfo) : void
        {
            var _loc_2:int = 0;
            var _loc_3:Array = null;
            var _loc_4:int = 0;
            _loc_2 = 0;
            while (_loc_2 < this._queues.length)
            {
                
                _loc_3 = this._queues[_loc_2] as Array;
                _loc_4 = _loc_3.indexOf(param1);
                if (_loc_4 != -1)
                {
                    _loc_3.splice(_loc_4, 1);
                    param1.isLoading = false;
                    param1.isLoaded = false;
                    this._completeCaller.removeCallByType(param1.name);
                    this._progressCaller.removeCallByType(param1.name);
                    this._errorCaller.removeCallByType(param1.name);
                    return;
                }
                _loc_2++;
            }
            return;
        }// end function

        public static function get instance() : LoaderManager
        {
            return _instance;
        }// end function

    }
}
